class Blackboard {
  app: CanvasRenderingContext2D
  // 定义存放按钮的div
  div:HTMLDivElement = document.createElement('div')
  // 定义画布背景颜色
  bgColor: string = 'gray'
  // 画笔颜色和宽度
  penColor: string = 'green'
  penWidth: number = 1
  // 颜色数组
  color:Array<string> = ['red', 'green', 'blue', 'yellow', 'black', 'pink', 'gray']

  // public 使其成为类的属性 可在其他地方使用this调用 不加的话就是形参
  constructor(public el = document.querySelector<HTMLCanvasElement>("#canvas" ), public height: number = el.height, public width: number = el.width) {
    // 跟上面使用public修饰符一样 只不过这里单独写出来
    this.app = el.getContext('2d')
    // 画布初始化
    this.initCanvas()
    // 绑定事件
    this.bindEvent()
    // 添加清屏按钮和事件
    this.addBtn()
  }

  // 画布初始化
  private initCanvas() {
    this.app.fillStyle = this.bgColor
    this.app.fillRect(0, 0, this.width, this.height)
  }

  // 添加清屏按钮和事件
  private addBtn() {
    // afterend: 在canvas外面添加一个div
    this.el.insertAdjacentElement('afterend', this.div)
    this.div.style.cssText = 'margin: 10px; display: flex'
    // 创建一个按钮
    const clearBtn = document.createElement('button')
    clearBtn.innerText = '擦黑板'
    // afterbegin 在div里面添加
    this.div.insertAdjacentElement('afterbegin', clearBtn)
    // 给按钮绑定事件 清除黑板
    clearBtn.addEventListener('click', () => {
      this.app.fillStyle = this.bgColor
      this.app.fillRect(0, 0, this.el.width, this.el.height)
    })
  }

  // 绑定鼠标按下事件
  private bindEvent() {
    const callback = this.drawLine.bind(this)
    this.el.addEventListener('mousedown', (e:MouseEvent) => {
      this.app.beginPath()
      // 画笔颜色
      this.app.lineWidth = this.penWidth
      this.app.strokeStyle = this.penColor
      // 鼠标移动划线
      this.el.addEventListener('mousemove', callback)
      // 移除事件 为了在鼠标移出黑板的时候松开能成功移除事件 所以绑定在doc上
      document.addEventListener('mouseup', () => {
        this.el.removeEventListener('mousemove', callback)
      })
    })
  }

  // 鼠标移动划线
  private drawLine(e:MouseEvent) {
    this.app.lineTo(e.offsetX, e.offsetY)
    this.app.stroke()
  }

  // 更改画布背景颜色的按钮和事件
  public setBgColor() {
    // 生成一个div包裹颜色选择器
    const colorDivContainer = document.createElement('div')
    colorDivContainer.classList.add('color-picker')
    this.div.insertAdjacentElement('afterbegin', colorDivContainer)
    // 生成颜色选择器
    this.color.forEach((curColor) => {
      const colorPicker = document.createElement('div')
      colorPicker.style.cssText = `width: 24.4px; height: 24.4px; background-color: ${curColor}`
      colorDivContainer.insertAdjacentElement('afterbegin', colorPicker)
      colorPicker.addEventListener('click', () => {
        // 解决更换背景后 橡皮擦的问题
        this.bgColor = curColor
        this.penWidth = 1
        this.app.fillStyle = curColor
        this.app.fillRect(0, 0, this.el.width, this.el.height)
      })
    })
    // 链式调用
    return this
  }

  // 修改画笔颜色
  public setPenColor() {
    // 生成按钮
    const btn = document.createElement('button')
    btn.innerText = '修改画笔颜色'
    this.div.insertAdjacentElement('afterbegin', btn)
    // 随机颜色
    setInterval(() => {
      let color: string = this.color.sort(() => Math.random() - 0.5)[0]
      btn.style.cssText = `background-color: ${color}; border: 1px solid gray; margin-left: 10px`
      btn.addEventListener('click', () => {
        this.penWidth = 1
        this.penColor = color
      })
    }, 2000)
    // 链式调用
    return this
  }

  // 橡皮擦
  public clearLine() {
    // 生成按钮
    const btn = document.createElement('button')
    btn.innerText = '胶擦'
    this.div.insertAdjacentElement('afterbegin', btn)
    btn.addEventListener('click', () => {
      this.penWidth = 15
      this.penColor = this.bgColor
    })
    // 链式调用
    return this
  }

  // 截图
  public sort() {
    // 生成按钮
    const btn = document.createElement('button')
    btn.innerText = '截图'
    btn.style.cssText = 'margin-right: 10px'
    this.div.insertAdjacentElement('afterbegin', btn)
    btn.addEventListener('click', () => {
      // 先清除id为img的图片
      const imgLast = document.getElementById('img')
      if (imgLast) {
        imgLast.remove()
      }
      // 思路是创建img标签 使用base64保存图片
      const img = document.createElement('img')
      img.src = this.el.toDataURL('image/jpeg')
      img.width = 150
      img.height = 150
      // 添加id
      img.id = 'img'
      document.body.append(img)
    })
    // 链式调用
    return this
  }
}

const instance = new Blackboard()
// 也可以在外面调用公共方法
instance.setBgColor().setPenColor().clearLine().sort()
